﻿using NineSeas.Services;
using Orchard;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Security;
using Orchard.Services;
using Orchard.Mvc;
using System.Web.Mvc;
using Orchard.Themes;
using NineSeas.ViewModels;
using NineSeas.Models;
using System;
namespace NineSeas.Controllers
{
    public class ChapterController : Controller, IUpdateModel
    {
        private readonly IAuthenticationService _authenticationService;
        private readonly IAuthorizationService _authorizationService;
        private readonly IOrchardServices _services;
        private readonly IClock _clock;
        private readonly IBookService _bookService;
        private readonly IChapterService _chapterService;
        private Localizer T { get; set; }

        public ChapterController(IOrchardServices services, 
                IAuthenticationService authenticationService,
                IAuthorizationService authorizationService,
                IClock clock,
                IBookService bookService,
                IChapterService chapterService)
        {
            this._services = services;
            this._authenticationService = authenticationService;
            this._authorizationService = authorizationService;
            this._clock = clock;
            this._bookService = bookService;
            this._chapterService = chapterService;
            T = NullLocalizer.Instance;
        }

        [Themed]
        public ActionResult Index(int bookId, PaginationInfo paging)
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
                throw new OrchardSecurityException(T("Login required"));

            dynamic bookPart = null;
            dynamic chapters = null;
            if (bookId >= 0)
            {
                bookPart = _services.ContentManager.Get<BookPart>(bookId, VersionOptions.Latest);
                chapters = _chapterService.GetByBookId(bookId, paging, VersionOptions.Latest);
            }
            
            return new ShapeResult(this, _services.New.Authoring_Book_Chapters_Index(
                    Book: bookPart,
                    Chapters: chapters,
                    Paging: paging
                ));
        }

        [Themed]
        public ActionResult Create(int bookId)
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
                throw new OrchardSecurityException(T("Login required"));

            var book = _services.ContentManager.Get<BookPart>(bookId, VersionOptions.Latest);
            if (book != null)
            {
                var lastUrl = String.Empty;

                var last = _chapterService.GetLast(bookId, VersionOptions.Latest);
                if (last != null)
                {
                    lastUrl = Url.Action("Edit", "Chapter", new { id = last.Id });
                }
                return new ShapeResult(this, _services.New.Authoring_Book_Chapter_Edit(
                    IsNew: true,
                    Chapter: new ChapterViewModel(),
                    Book: book,
                    PreviousUrl: lastUrl,
                    Chapters: _chapterService.GetByBookId(bookId)
                ));
            }
            else
            {
                return RedirectToAction("Index", "Books");
            }
        }
        [HttpPost, ActionName("Create")]
        [ValidateInput(false)]
        public ActionResult Create(int bookId, ChapterViewModel chapterViewModel)
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
                throw new OrchardSecurityException(T("Login required"));

            var id = -1;
            var errorMessage = String.Empty;
            var book = _services.ContentManager.Get<BookPart>(bookId, VersionOptions.DraftRequired);

            if (book != null)
            {
                var lastOrder = _chapterService.GetLastOrder(bookId, VersionOptions.Latest);
                if (!lastOrder.HasValue || lastOrder.Value < -1) lastOrder = -1;

                var chapterPart = _services.ContentManager.Create<ChapterPart>("Chapter", VersionOptions.Draft, c =>
                {
                    c.BookId = book.Id;
                    c.Title = chapterViewModel.Title;
                    c.Content = chapterViewModel.Content;
                    c.SortOrder = lastOrder + 1;
                });

                if (chapterPart != null)
                {
                    _services.ContentManager.UpdateEditor(chapterPart, this);                                       

                    id = chapterPart.Id;
                }
                else
                {
                    errorMessage = T("An error has occurred while trying to create this chapter. Please try again later.").Text;
                }
            }
            else
            {
                errorMessage = T("Database error. Please contact an administrator.").Text;
            }

            var success = String.IsNullOrEmpty(errorMessage) && id >= 0;

            return Json(new {                 
                success = success,
                editUrl = success ? Url.Action("Edit", "Chapter", new { id = id}) : "",
                errorMessage = errorMessage
            });
        }
        [Themed]
        public ActionResult Edit(int id)
        {
            if (!_services.Authorizer.Authorize(Permissions.AddBooks, T("You do not have the permission to this page.")))
            {
                return Redirect("~/");
            }
            var user = _authenticationService.GetAuthenticatedUser();
            
            var chapterViewModel = new ChapterViewModel();
            if (id >= 0)
            {
                var chapterPart = _services.ContentManager.Get<ChapterPart>(id, VersionOptions.Latest);
                chapterViewModel.Title = chapterPart.Title;
                chapterViewModel.Content = chapterPart.Content;
                chapterViewModel.SortOrder = chapterPart.SortOrder.HasValue ? chapterPart.SortOrder.Value : 0;

                var bookPart = _services.ContentManager.Get<BookPart>(chapterPart.BookId, VersionOptions.Latest);

                if (bookPart.AuthorId != user.Id
                        && !_services.Authorizer.Authorize(Permissions.ManageBooks, T("You do not have the permission to edit other's books.")))
                {
                    return Redirect("~/");
                }

                var nextUrl = String.Empty;
                var next = _chapterService.GetNext(chapterPart);
                if (next != null)
                {
                    nextUrl = Url.Action("Edit", "Chapter", new { id = next.Id });
                }
                else
                {
                    nextUrl = Url.Action("Create", "Chapter", new { bookId = bookPart.Id });
                }

                return new ShapeResult(this, _services.New.Authoring_Book_Chapter_Edit(
                    IsNew: false,
                    Id: id,
                    Chapter: chapterViewModel,
                    Book: bookPart,
                    Chapters: _chapterService.GetByBookId(bookPart.Id, VersionOptions.Latest),
                    PreviousUrl: GetPreviousUrl(chapterPart, bookPart),
                    NextUrl: GetNextUrl(chapterPart, bookPart)
                ));
            }

            return RedirectToAction("Index", "Books");      
        }


        [HttpPost, ActionName("Edit")]
        [ValidateInput(false)]
        public ActionResult Edit(int id, ChapterViewModel chapterViewModel)
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
                throw new OrchardSecurityException(T("Login required"));
                        
            var errorMessage = String.Empty;
            var chapterPart = _services.ContentManager.Get<ChapterPart>(id, VersionOptions.DraftRequired);

            if (chapterPart != null)
            {
                chapterPart.Title = chapterViewModel.Title;
                chapterPart.Content = chapterViewModel.Content;
                _services.ContentManager.UpdateEditor(chapterPart, this);

                // get the associated book and make it draft
                _services.ContentManager.Get<BookPart>(chapterPart.BookId, VersionOptions.DraftRequired);
            }
            else
            {
                errorMessage = T("Database error. Please contact an administrator.").Text;
            }

            var success = String.IsNullOrEmpty(errorMessage);

            return Json(new { 
                success = success,
                errorMessage = errorMessage
            });
        }
        public ActionResult MoveUp(int id)
        {
            _chapterService.Move(id, true);
            return RedirectToAction("Index", "Chapter"); 
        }
        public ActionResult MoveDown(int id)
        {
            _chapterService.Move(id, false);
            return RedirectToAction("Index", "Chapter"); 
        }

        public ActionResult Delete(int id)
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (_authenticationService.GetAuthenticatedUser() == null)
                throw new OrchardSecurityException(T("Login required"));

            var chapterPart = _chapterService.Get(id);
            var bookPart = chapterPart != null ? _services.ContentManager.Get<BookPart>(chapterPart.BookId) : null;

            if (bookPart != null
                && (bookPart.AuthorId == user.Id || _authorizationService.TryCheckAccess(Permissions.ManageBooks, user, bookPart)))
            {
                _chapterService.Delete(chapterPart);
            }
            else
            {
                throw new OrchardSecurityException(T("You don't have permission to perform this action."));
            }
            

            if (!String.IsNullOrEmpty(Request["ReturnUrl"]))
            {
                return Redirect(Request["ReturnUrl"]);
            }
            else
            {
                return RedirectToAction("Index", "Chapter"); 
            }
        }

        private string GetNextUrl(ChapterPart chapter, BookPart book)
        {
            var nextUrl = String.Empty;
            var next = _chapterService.GetNext(chapter);
            if (next != null)
            {
                nextUrl = Url.Action("Edit", "Chapter", new { id = next.Id });
            }
            else
            {
                nextUrl = Url.Action("Create", "Chapter", new { bookId = book.Id });
            }

            return nextUrl;
        }
        private string GetPreviousUrl(ChapterPart chapter, BookPart book)
        {
            var previousUrl = String.Empty;
            var previous = _chapterService.GetPrevious(chapter);
            if (previous != null)
            {
                previousUrl = Url.Action("Edit", "Chapter", new { id = previous.Id });
            }

            return previousUrl;
        }

        bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
        {
            return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
        }

        void IUpdateModel.AddModelError(string key, LocalizedString errorMessage)
        {
            ModelState.AddModelError(key, errorMessage.ToString());
        }
    }
}